﻿package src.tools{
	import flash.geom.Point;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.ColorTransform;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.ByteArray;
	import flash.display.DisplayObject;
	import flash.display.BitmapData;
	import flash.errors.EOFError;
	
    public class HitTester{
        public static function hitTestObject(item1:DisplayObject, item2:DisplayObject):Boolean {
			if (item1.hitTestObject(item2) ) {
			
				var colorTransform1			:ColorTransform;
				var colorTransform2			:ColorTransform;
				var item1Registration		:Point;
				var item2Registration		:Point;
				var bmd1					:BitmapData;
				var bmd2					:BitmapData;
				var rect1					:Rectangle;
				var rect2					:Rectangle;
			
				var transMatrix1			:Matrix;
				var transMatrix2			:Matrix;
				
				var pixels1					:ByteArray;
				var pixels2					:ByteArray;
				var _alphaThreshold			:Number;
				
				var item1xDiff:Number, item1yDiff:Number;
				
				_alphaThreshold = 0;
				
	
				colorTransform1 = item1.transform.colorTransform;
				colorTransform2 = item2.transform.colorTransform;
				
				item1Registration = new Point();
				item2Registration = new Point();
	
				item1Registration = item1.localToGlobal(item1Registration);
				item2Registration = item2.localToGlobal(item2Registration);
				
				bmd1 = new BitmapData(item1.width, item1.height, true, 0x00FFFFFF);  
				bmd2 = new BitmapData(item1.width, item1.height, true, 0x00FFFFFF);
				
				
				transMatrix1 = item1.transform.matrix;
				
				var currentObj = item1;
				while(currentObj.parent != null)
				{
					transMatrix1.concat(currentObj.parent.transform.matrix);
					currentObj = currentObj.parent;
				}
				
				rect1 = item1.getBounds(currentObj);
				if(item1 != currentObj)
				{
					rect1.x += currentObj.x;
					rect1.y += currentObj.y;
				}
				
				transMatrix1.tx = item1xDiff = (item1Registration.x - rect1.left);
				transMatrix1.ty = item1yDiff = (item1Registration.y - rect1.top);
				
				transMatrix2 = item2.transform.matrix;
				
				currentObj = item2;
				while(currentObj.parent != null)
				{
					transMatrix2.concat(currentObj.parent.transform.matrix);
					currentObj = currentObj.parent;
				}
				
				transMatrix2.tx = (item2Registration.x - rect1.left);
				transMatrix2.ty = (item2Registration.y - rect1.top);
				
				bmd1.draw(item1, transMatrix1, colorTransform1, null, null, true);
				bmd2.draw(item2, transMatrix2, colorTransform2, null, null, true);
				
				pixels1 = bmd1.getPixels(new Rectangle(0, 0, bmd1.width, bmd1.height));
				pixels2 = bmd2.getPixels(new Rectangle(0, 0, bmd1.width, bmd1.height));	
				
				var k:uint = 0, value1:uint = 0, value2:uint = 0, collisionPoint:Number = -1, overlap:Boolean = false, overlapping:Array = [];
				var locY:Number, locX:Number, locStage:Point;
				
				pixels1.position = 0;
				pixels2.position = 0;
				
				var pixelLength:int = pixels1.length;
				while(k < pixelLength)
				{
					k = pixels1.position;
					
					try
					{
						value1 = pixels1.readUnsignedInt();
						value2 = pixels2.readUnsignedInt();
					}
					catch(e:EOFError)
					{
						break;
					}
					
					var alpha1:uint = value1 >> 24 & 0xFF, alpha2:uint = value2 >> 24 & 0xFF;
					if(alpha1 > _alphaThreshold && alpha2 > _alphaThreshold)
					{	
						return true;
					}
				}
			}
			return false;
        }
		
		public static function hitTestPoint(object:DisplayObject, point:Point):Boolean {
            if(object is BitmapData) {
                return (object as BitmapData).hitTest(new Point(0,0), 0, object.globalToLocal(point));
            }
            else {
                if(!object.hitTestPoint(point.x, point.y, true)) {
                    return false;
                }
                else {
                    var bmapData:BitmapData = new BitmapData(object.width, object.height, true, 0x00000000);
                    bmapData.draw(object, new Matrix());
                    var returnVal:Boolean = bmapData.hitTest(new Point(0,0), 0, object.globalToLocal(point));
                    bmapData.dispose();
                    return returnVal;
                }
            }
        }
		
    }
}